package com.example.api.sentinel;

import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.AbstractRule;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import com.alibaba.fastjson.JSON;
import com.example.common.entity.ResultDO;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Service
public class CustomUrlBlockHandler implements BlockExceptionHandler {

    private static final Logger logger = LoggerFactory.getLogger(FallbackHandlerResponse.class);

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
        ResultDO resultDO = null;
        if(e instanceof FlowException){
            FlowException ex = (FlowException) e;
            logger.warn("sentinel  FlowException  触发资源限流规则 {}",getResourceInfo(ex.getRule()));
            resultDO =  new ResultDO(false, "当前访问人数过多，请稍后再试!");
        }else if(e instanceof DegradeException){
            DegradeException ex = (DegradeException) e;
            logger.warn("sentinel DegradeException {} 触发资源降级 {}",e.getMessage(),getResourceInfo(ex.getRule()));
            resultDO = new ResultDO(false, "服务出现异常，请稍后再试~");
        }else if (e instanceof SystemBlockException) {
            SystemBlockException ex = (SystemBlockException) e;
            logger.warn("sentinel  SystemBlockException {} 触发系统保护规则 {}",e.getMessage(),getResourceInfo(ex.getRule()));
            resultDO =  new ResultDO(false, "系统出现异常，请稍后再试~");
        } else if(e instanceof ParamFlowException){
            ParamFlowException ex = (ParamFlowException) e;
            logger.warn("sentinel ParamFlowException 热点参数限流 资源名={} 参数={} {}", ex.getResourceName(), ex.getLimitParam(), getResourceInfo(ex.getRule()));
            resultDO =  new ResultDO(false, "热点参数限流" + e.getMessage());
        } else if(e instanceof AuthorityException){
            AuthorityException ex = (AuthorityException) e;
            logger.warn("sentinel AuthorityException 授权规则不通过 {}", getResourceInfo(ex.getRule()));
            resultDO =  new ResultDO(false, "授权规则不通过");
        }
        // http状态码
        response.setStatus(403);
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-Type", "application/json;charset=utf-8");
        response.setContentType("application/json;charset=utf-8");
        new ObjectMapper().writeValue(response.getWriter(), resultDO);
    }



    public static  String  getResourceInfo(AbstractRule rule){
        String  origin = rule.getLimitApp();
        String resource = rule.getResource();
        return String.format("资源名称:%s, 调用方:%s, 规则:%s", resource, origin,  JSON.toJSONString(rule));
    }

}